package com.eflow.engine.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.eflow.engine.cmd.RejectedCmd;
import com.eflow.engine.handler.ProcessListenerHandler;
import com.eflow.engine.service.IEflowRepositoryServiceService;
import com.eflow.engine.service.IEflowTaskService;
import com.eflow.model.flowable.model.ButtonElement;
import com.eflow.model.flowable.model.UserTaskExtendElement;
import com.eflow.model.service.IEflowUserService;
import com.eflow.engine.service.ITaskService;
import com.eflow.engine.vo.*;
import com.eflow.model.domain.EflowTask;
import com.eflow.model.domain.EflowUser;
import com.eflow.model.e.BpmConst;
import com.eflow.model.e.CommentTypeEnum;
import com.eflow.model.e.TaskStatus;
import com.eflow.model.expetion.FlowableException;
import com.eflow.model.utils.FlowUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.Activity;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hui se
 * @description
 * @create 2021-02-26 11:38
 * @Auther JanHezz
 * @BLOG www.luckyhe.com
 * @DATE 2021/3/3 17:05
 **/

@Slf4j
@Transactional(rollbackFor = Exception.class)
public class TaskServiceImpl extends AbstractEflowService implements ITaskService, BpmConst {

    @Autowired
    IEflowRepositoryServiceService eflowRepositoryServiceService;

    @Autowired
    IEflowUserService eflowUserService;

    @Autowired
    private IEflowTaskService eflowTaskService;

    @Autowired
    private ProcessListenerHandler processListener;

    @Override
    public void complete(CompleteTaskVo params) {
        if (StringUtils.isBlank(params.getTaskId())) {
            throw new FlowableException("任务Id不能为空");
        }
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(params.getTaskId()).singleResult();
        if (params.getVariables() == null) {
            params.setVariables(new HashMap<>());
        }
        Map<String, Object> localVar = new HashMap();
        localVar.put(VAR_TASK_COMMENT, params.getMessage());
        localVar.put(SKIP_LIST, params.getSkipList());
        params.getVariables().putAll(params.getUserListMap());
        if (taskEntity != null) {
            {
                String taskId = params.getTaskId();
                //2.委派处理
                if (DelegationState.PENDING.equals(taskEntity.getDelegationState())) {
                    //2.1生成历史记录
                    TaskEntity task = this.createSubTask(taskEntity, Authentication.getAuthenticatedUserId());
                    taskService.complete(task.getId());
                    taskId = task.getId();
                    //2.2执行委派
                    taskService.resolveTask(params.getTaskId(), params.getVariables());
                } else {
                    //3.2执行任务
                    taskService.complete(params.getTaskId(), params.getVariables(), localVar);
                    //4.处理加签父任务
                    String parentTaskId = taskEntity.getParentTaskId();
                    if (StringUtils.isNotBlank(parentTaskId)) {
                        String tableName = managementService.getTableName(TaskEntity.class);
                        String sql = "select count(1) from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";
                        long subTaskCount = taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count();
                        if (subTaskCount == 0) {
                            Task task = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
                            //处理前后加签的任务
                            taskService.resolveTask(parentTaskId);
                            if (AFTER_ADDSIGN.equals(task.getScopeType())) {
                                taskService.complete(parentTaskId);
                            }
                        }
                    }
                }
                if (StrUtil.isBlank(params.getMessage())) {
                    params.setMessage("[同意]");
                }
                //5.生成审批意见
                this.addComment(taskId, Authentication.getAuthenticatedUserId(), params.getProcessInstanceId(), CommentTypeEnum.APPROVE, params.getMessage());
            }
        } else {
            throw new FlowableException("未找到该任务");
        }
    }

    /**
     * 驳回流程到任意步骤
     *
     * @param jumpTaskVo 参数
     * @return
     */
    @Override
    public void jumpToSelectStep(JumpTaskVo jumpTaskVo) {
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(jumpTaskVo.getTaskId()).singleResult();
        //1.把当前的节点设置为空
        if (taskEntity == null) {
            throw new FlowableException("不存在任务实例,请确认!");
        }
        //5.删除节点
        this.deleteActivity(jumpTaskVo.getActivityId(), taskEntity.getProcessInstanceId());
        jumpTaskVo.setAdmin(true);
       this.moveChange(jumpTaskVo);
    }

    @Override
    public TaskEntity moveChange(JumpTaskVo jumpTaskVo) {
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(jumpTaskVo.getTaskId()).singleResult();
        //1.把当前的节点设置为空
        if (taskEntity != null) {

            //3.添加驳回意见
            if(!jumpTaskVo.getAdmin()){
                this.addComment(jumpTaskVo.getTaskId(), Authentication.getAuthenticatedUserId(), taskEntity.getProcessInstanceId(),
                        CommentTypeEnum.RETURN, jumpTaskVo.getMessage());
            }else {
                if(jumpTaskVo.getAddMessage()){
                    this.addComment(jumpTaskVo.getTaskId(), Authentication.getAuthenticatedUserId(), taskEntity.getProcessInstanceId(),
                            CommentTypeEnum.ADMIN, jumpTaskVo.getMessage());
                }else {
                    this.addComment(jumpTaskVo.getTaskId(), Authentication.getAuthenticatedUserId(), taskEntity.getProcessInstanceId(),
                            CommentTypeEnum.APPROVE, jumpTaskVo.getMessage());
                }
            }

            int count = eflowTaskService.count(Wrappers.lambdaQuery(EflowTask.class).eq(EflowTask::getProcessInstanceId, taskEntity.getProcessInstanceId()).ne(EflowTask::getTaskId, taskEntity.getId()).eq(EflowTask::getStatus, TaskStatus.WAIT.getCode()));
            //这里处理多实例退回其他未审批的用户还有待办的情况
            if (count > 0) {
                eflowTaskService.remove(Wrappers.lambdaQuery(EflowTask.class).eq(EflowTask::getProcessInstanceId, taskEntity.getProcessInstanceId()).ne(EflowTask::getTaskId, taskEntity.getId()).eq(EflowTask::getStatus, TaskStatus.WAIT.getCode()));
            }
            Map<String, Object> variables = new HashMap<>();
            variables.putAll(jumpTaskVo.getUserListMap());
            List<String> executionIds = new ArrayList<>();
            //6.判断节点是不是子流程内部的节点
            if (eflowRepositoryServiceService.checkActivitySubprocessByActivityId(taskEntity.getProcessDefinitionId(),
                    jumpTaskVo.getActivityId())
                    && eflowRepositoryServiceService.checkActivitySubprocessByActivityId(taskEntity.getProcessDefinitionId(),
                    taskEntity.getTaskDefinitionKey())) {
                //6.1 子流程内部驳回
                Execution executionTask = runtimeService.createExecutionQuery().executionId(taskEntity.getExecutionId()).singleResult();
                String parentId = executionTask.getParentId();
                List<Execution> executions = runtimeService.createExecutionQuery().parentId(parentId).list();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                this.moveExecutionsToSingleActivityId(executionIds, jumpTaskVo.getActivityId(), variables);
            } else {
                //6.2 普通驳回
                List<Execution> executions = runtimeService.createExecutionQuery().parentId(taskEntity.getProcessInstanceId()).list();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                this.moveExecutionsToSingleActivityId(executionIds, jumpTaskVo.getActivityId(), variables);
            }
        } else {
            throw new FlowableException("不存在任务实例,请确认!");
        }
        return taskEntity;
    }

    //TODO 这个方法还有问题，最好使用遍历流程模型去获取可驳回的点
    @Override
    public List<TaskNodeVo> getBackNodesByProcessInstanceId(String processInstanceId, String taskId) {
        List<ActHisNode> backNods = new ArrayList<>();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new FlowableException("当前任务不存在");
        }
        String currActId = task.getTaskDefinitionKey();
        FlowElement element = FlowUtil.getFlowElementById(repositoryService, task.getProcessDefinitionId(), currActId);
        UserTaskExtendElement currUserTask = UserTaskExtendElement.parse(element);
        //获取运行节点表中usertask
        String sql = "select t.* from act_ru_actinst t where t.ACT_TYPE_ = 'userTask' " +
                " and t.PROC_INST_ID_=#{processInstanceId} and t.END_TIME_ is not null ";
        List<ActivityInstance> activityInstances = runtimeService.createNativeActivityInstanceQuery().sql(sql)
                .parameter("processInstanceId", processInstanceId)
                .list();
        //获取运行节点表的parallelGateway节点并出重
        sql = "SELECT t.ID_, t.REV_,t.PROC_DEF_ID_,t.PROC_INST_ID_,t.EXECUTION_ID_,t.ACT_ID_, t.TASK_ID_, t.CALL_PROC_INST_ID_, t.ACT_NAME_, t.ACT_TYPE_, " +
                " t.ASSIGNEE_, t.START_TIME_, max(t.END_TIME_) as END_TIME_, t.DURATION_, t.DELETE_REASON_, t.TENANT_ID_" +
                " FROM  act_ru_actinst t WHERE t.ACT_TYPE_ in ('parallelGateway','subProcess') AND t.PROC_INST_ID_ = #{processInstanceId} and t.END_TIME_ is not null" +
                " and t.ACT_ID_ <> #{actId} GROUP BY T.ID_,T.REV_,T.PROC_DEF_ID_,T.PROC_INST_ID_,T.EXECUTION_ID_,T.ACT_ID_,T.TASK_ID_,T.CALL_PROC_INST_ID_,T.ACT_NAME_,T.ACT_TYPE_,T.ASSIGNEE_,T.START_TIME_,T.DURATION_,T.DELETE_REASON_, t.TENANT_ID_";
        List<ActivityInstance> parallelGatewaies = runtimeService.createNativeActivityInstanceQuery().sql(sql)
                .parameter("processInstanceId", processInstanceId)
                .parameter("actId", currActId)
                .list();
        //排序
        if (CollectionUtil.isNotEmpty(parallelGatewaies)) {
            activityInstances.addAll(parallelGatewaies);
            activityInstances.sort(Comparator.comparing(ActivityInstance::getEndTime));
        }
        //分组节点
        int gatewayCount = 0, subProcessCount = 0;
        List<ActivityInstance> userTasks = new ArrayList<>();
        for (ActivityInstance activityInstance : activityInstances) {
            if (BpmnXMLConstants.ELEMENT_GATEWAY_PARALLEL.equals(activityInstance.getActivityType())) {
                gatewayCount++;
            }
            if (BpmnXMLConstants.ELEMENT_SUBPROCESS.equals(activityInstance.getActivityType())) {
                subProcessCount++;
            }
            if (BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType())) {
                if (gatewayCount % 2 == 0 && subProcessCount % 2 == 0) {
                    userTasks.add(activityInstance);
                }
            }
        }
        //过滤出模型中配置的节点
        List<ActivityInstance> list = userTasks.stream().filter(x -> currUserTask.getRejectNodes().stream().anyMatch(e -> x.getActivityId().equals(e.getId()))).collect(Collectors.toList());

        //组装人员名称
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId).finished().list();
        Map<String, List<HistoricTaskInstance>> taskInstanceMap = new HashMap<>();
        List<String> userCodes = new ArrayList<>();
        historicTaskInstances.forEach(historicTaskInstance -> {
            userCodes.add(historicTaskInstance.getAssignee());
            String taskDefinitionKey = historicTaskInstance.getTaskDefinitionKey();
            if (taskInstanceMap.containsKey(historicTaskInstance.getTaskDefinitionKey())) {
                taskInstanceMap.get(taskDefinitionKey).add(historicTaskInstance);
            } else {
                List<HistoricTaskInstance> tasks = new ArrayList<>();
                tasks.add(historicTaskInstance);
                taskInstanceMap.put(taskDefinitionKey, tasks);
            }
        });


        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(activityInstance -> {
                ActHisNode node = new ActHisNode();
                node.setNodeId(activityInstance.getActivityId());
                node.setNodeName(activityInstance.getActivityName());
                node.setEndTime(activityInstance.getEndTime());
                backNods.add(node);
            });
        }

        //去重合并
        List<ActHisNode> datas = backNods.stream().collect(
                Collectors.collectingAndThen(Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(ActHisNode::getNodeId))), ArrayList::new));

        //排序
        datas.sort(Comparator.comparing(ActHisNode::getEndTime));
        List<Activity> userList = datas.stream().map(x -> {
            FlowElement flowElement = FlowUtil.getFlowElementById(repositoryService, task.getProcessDefinitionId(), x.getNodeId());
            if (flowElement instanceof UserTask) {
                return (UserTask) flowElement;
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).active()
                .singleResult();


        return getTaskNode(processDefinition, task.getProcessInstanceId(), taskService.getVariables(taskId), userList);
    }

    @Override
    public void delegateTask(DelegateTaskVo delegateTaskVo) {

        TaskEntityImpl currTask = (TaskEntityImpl) taskService.createTaskQuery().
                taskId(delegateTaskVo.getTaskId()).singleResult();
        if (currTask != null) {
            //1.添加审批意见
            this.addComment(delegateTaskVo.getTaskId(), Authentication.getAuthenticatedUserId(), delegateTaskVo.getProcessInstanceId(),
                    CommentTypeEnum.DELEGATE, delegateTaskVo.getMessage());
            //2.设置审批人就是当前登录人
            taskService.setAssignee(delegateTaskVo.getTaskId(), Authentication.getAuthenticatedUserId());
            //3.执行委派
            taskService.delegateTask(delegateTaskVo.getTaskId(), delegateTaskVo.getDelegateUserId());

            //4.设置任务所有者
            taskService.setOwner(delegateTaskVo.getTaskId(), Authentication.getAuthenticatedUserId());

        } else {
            throw new FlowableException("没有运行时的任务实例");
        }

    }

    @Override
    public void turnTask(TurnTaskVo turnTaskVo) {
        TaskEntityImpl currTask = (TaskEntityImpl) taskService.createTaskQuery().taskId(turnTaskVo.getTaskId()).singleResult();

        if (currTask != null) {
            if (turnTaskVo.getTurnToUserId().equals(currTask.getAssignee())) {
                throw new FlowableException("待转办人与审批人一致");
            }
            if (turnTaskVo.getAddMessage()) {
                if (StrUtil.isBlank(turnTaskVo.getMessage())) {
                    EflowUser turnUser = eflowUserService.selectUserByUserId(turnTaskVo.getTurnToUserId());
                    EflowUser assignee = eflowUserService.selectUserByUserId(currTask.getAssignee());
                    turnTaskVo.setMessage(StrUtil.indexedFormat("由【{0}】转办给【{1}】",
                            assignee.getNickName(), turnUser.getNickName()
                    ));
                }
                //2.添加审批意见
                this.turnComment(currTask, turnTaskVo.getMessage());
            }
            //3.转办
            taskService.setAssignee(turnTaskVo.getTaskId(), turnTaskVo.getTurnToUserId());
            taskService.setOwner(turnTaskVo.getTaskId(), Authentication.getAuthenticatedUserId());

        } else {
            throw new FlowableException("没有运行时的任务实例");
        }
    }

    /**
     * 将历史待办设置为转办
     * 插入新的待办，这样更换了审批人在待办列表也是最后一条
     *
     * @param task
     * @param message
     */
    private void turnComment(TaskEntity task, String message) {
        EflowTask eflowTask = eflowTaskService.getOne(Wrappers.lambdaQuery(EflowTask.class)
                .eq(EflowTask::getTaskId, task.getId()));
        eflowTaskService.update(Wrappers.lambdaUpdate(EflowTask.class)
                .set(EflowTask::getStatus, TaskStatus.END.getCode())
                .set(EflowTask::getComments, message)
                .set(EflowTask::getEndDate, new Date())
                .set(EflowTask::getTaskId, task.getId() + "_" + "turn")
                .set(EflowTask::getActivityId, task.getTaskDefinitionKey() + "_" + "turn")
                .set(EflowTask::getCommentType, CommentTypeEnum.TURN_TODO.getCode())
                .eq(EflowTask::getTaskId, task.getId()));
        eflowTask.setId(null);
        eflowTask.setStartDate(new Date());
        eflowTask.setCreateTime(null);
        eflowTask.setUpdateTime(null);
        eflowTaskService.save(eflowTask);
    }

    protected TaskEntity createSubTask(TaskEntity ptask, String assignee) {
        return this.createSubTask(ptask, ptask.getId(), assignee);
    }

    /**
     * 创建子任务
     *
     * @param ptask    创建子任务
     * @param assignee 子任务的执行人
     * @return
     */
    protected TaskEntity createSubTask(TaskEntity ptask, String ptaskId, String assignee) {
        TaskEntity task = null;
        if (ptask != null) {
            //1.生成子任务
            task = (TaskEntity) taskService.newTask();
            task.setCategory(ptask.getCategory());
            task.setDescription(ptask.getDescription());
            task.setTenantId(ptask.getTenantId());
            task.setAssignee(assignee);
            task.setName(ptask.getName());
            task.setParentTaskId(ptaskId);
            task.setExecutionId(ptask.getExecutionId());
            task.setProcessDefinitionId(ptask.getProcessDefinitionId());
            task.setProcessInstanceId(ptask.getProcessInstanceId());
            task.setTaskDefinitionKey(ptask.getTaskDefinitionKey());
            task.setTaskDefinitionId(ptask.getTaskDefinitionId());
            task.setPriority(ptask.getPriority());
            task.setCreateTime(new Date());
            taskService.saveTask(task);
        }
        return task;
    }

    @Override
    public void revokeProcess(RevokeVo revokeVo) {
        if (StringUtils.isNotBlank(revokeVo.getProcessInstanceId())) {
            throw new FlowableException("流程实例id不能为空");
        }
        if (StringUtils.isNotBlank(revokeVo.getTaskId())) {
            throw new FlowableException("任务id不能为空");
        }

        //找到当前任务的节点id
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().
                taskId(revokeVo.getTaskId()).
                finished().singleResult();
        if (historicTaskInstance == null) {
            throw new FlowableException("");
        }
        //判断当前节点的下一节点是否已处理
        //获取运行节点表中usertask
        String sql = "select t.* from act_ru_actinst t where t.ACT_TYPE_ = 'userTask' " +
                " and t.PROC_INST_ID_=#{processInstanceId} and t.END_TIME_ is not null" +
                " and t.ACT_ID_ <> #{actId}" +
                " and t.END_TIME_ > #{endTime}";
        List<ActivityInstance> activityInstances = runtimeService.createNativeActivityInstanceQuery().sql(sql)
                .parameter("processInstanceId", revokeVo.getProcessInstanceId())
                .parameter("endTime", historicTaskInstance.getEndTime())
                .parameter("actId", historicTaskInstance.getTaskDefinitionKey())
                .list();
        if (CollectionUtil.isNotEmpty(activityInstances)) {
            throw new FlowableException("后续流程已被处理,不能撤回!");
        } else {
            this.deleteActivity(historicTaskInstance
                    .getTaskDefinitionKey(), revokeVo.getProcessInstanceId());
            //5.执行跳转
            List<Execution> executions = runtimeService.createExecutionQuery().parentId(revokeVo.getProcessInstanceId()).list();
            List<String> executionIds = new ArrayList<>();
            executions.forEach(execution -> executionIds.add(execution.getId()));
            this.moveExecutionsToSingleActivityId(executionIds, historicTaskInstance.getTaskDefinitionKey());
        }

    }


    @Override
    public void backProcess(BackVo backVo) {
        if (StringUtils.isNotBlank(backVo.getProcessInstanceId())) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(backVo.getProcessInstanceId()).singleResult();
            if (processInstance != null) {
                //1.添加撤回意见
                this.addComment(Authentication.getAuthenticatedUserId(), backVo.getProcessInstanceId(), CommentTypeEnum.BACK, backVo.getMessage());
                //2.设置提交人
                runtimeService.setVariable(backVo.getProcessInstanceId(),
                        BpmConst.FLOW_SUBMIT_TASK_VAL, processInstance.getStartUserId());
                //3.执行撤回
                FlowNode disActivity = eflowRepositoryServiceService.findFlowNodeByName(processInstance.getProcessDefinitionId(), BpmConst.FLOW_SUBMIT_TASK_VAL);
                //4.删除运行和历史的节点信息
                this.deleteActivity(disActivity.getId(), backVo.getProcessInstanceId());
                //5.执行跳转
                List<Execution> executions = runtimeService.createExecutionQuery().parentId(backVo.getProcessInstanceId()).list();
                List<String> executionIds = new ArrayList<>();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                this.moveExecutionsToSingleActivityId(executionIds, disActivity.getId());
            }
        } else {
            throw new FlowableException("流程实例id不能为空");
        }
    }


    @Override
    public List<TaskNodeVo> getNextTaskNodeVoByTaskId(String taskId, Map<String, Object> variables) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new FlowableException("当前任务不存在");
        }
        Map<String, Object> objectObjectHashMap = new HashMap<>();
        Map<String, Object> taskVariables = taskService.getVariables(taskId);
        if (taskVariables != null) {
            objectObjectHashMap.putAll(taskVariables);
        }
        if (variables != null) {
            objectObjectHashMap.putAll(variables);
        }
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).active()
                .singleResult();
        if (processDefinition == null) {
            throw new FlowableException("流程不存在或被挂起");
        }
        String businessKey = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getBusinessKey();
        //设置流程开始的变量
        Process process = FlowUtil.getProcess(repositoryService, processDefinition.getId());
        processListener.handle((next) -> {
            Map<String, Object> vars = next.getVariables(businessKey);
            if (vars != null) {
                objectObjectHashMap.putAll(vars);
            }
            return true;
        }, process.getId());
        List<Activity> nextUserTasks = FlowUtil.getNextUserTasks(repositoryService, processDefinition, task.getTaskDefinitionKey(), objectObjectHashMap);
        List<TaskNodeVo> taskNode = getTaskNode(processDefinition, task.getProcessInstanceId(), objectObjectHashMap, nextUserTasks);
        setSkipTask(processDefinition, objectObjectHashMap, taskNode);
        return taskNode;
    }

    private List<TaskNodeVo> getTaskNode(ProcessDefinition processDefinition, String processInstanceId, Map<String, Object> objectObjectHashMap, List<Activity> nextUserTasks) {
        return nextUserTasks.stream().map(x -> {
            // 获取登录用户  identityService.setAuthenticatedUserId() 设置;
            String loginUser = Authentication.getAuthenticatedUserId();
            TaskNodeVo taskNodeVo = new TaskNodeVo();
            taskNodeVo.setName(x.getName());
            taskNodeVo.setNodeId(x.getId());
            taskNodeVo.setMultiInstance(x.getLoopCharacteristics() != null);
            UserTaskExtendElement element = UserTaskExtendElement.parse(x);
            taskNodeVo.setSetType(element.getSetType());
            List<EflowUser> userList = element.parseUserList(loginUser, processDefinition, processInstanceId, x.getId(), objectObjectHashMap);
            Map<String, String> groupMap = new HashMap<>();
            for (EflowUser eflowUser : userList) {
                if (StrUtil.isNotBlank(eflowUser.getGroupCode()) && !groupMap.containsKey(eflowUser.getGroupCode())) {
                    groupMap.put(eflowUser.getGroupCode(), eflowUser.getGroupName());
                }
            }
            taskNodeVo.setUserList(userList);
            taskNodeVo.setGroupMap(groupMap);
            return taskNodeVo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<TaskNodeVo> getOneStepTaskNodeVoByProcessDefinitionId(String businessKey, String processDefinitionId, Map<String, Object> variables) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).active().singleResult();
        if (processDefinition == null) {
            throw new FlowableException("流程不存在或被挂起");
        }
        return getOneStepUserTasks(businessKey, processDefinition, variables);
    }

    @Override
    public List<TaskNodeVo> getOneStepTaskNodeVoByProcessDefinitionKey(String businessKey, String processDefinitionKey, Map<String, Object> variables) {
        if (StrUtil.isBlank(processDefinitionKey)) {
            throw new FlowableException("流程key不能为空");
        }
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey).active()
                .latestVersion().singleResult();
        if (processDefinition == null) {
            throw new FlowableException("流程不存在或被挂起");
        }
        return getOneStepUserTasks(businessKey, processDefinition, variables);
    }

    @Override
    public List<ButtonElement> getButtonList(String taskId) {
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
        if (taskEntity == null) {
            throw new FlowableException("任务不存在");
        }
        UserTask userTask = (UserTask) FlowUtil.getFlowElementById(repositoryService, taskEntity.getProcessDefinitionId(), taskEntity.getTaskDefinitionKey());
        UserTaskExtendElement element = UserTaskExtendElement.parse(userTask);
        return element.getButtonList();
    }

    @Override
    public String getProcessInstanceIdByBusinessId(String businessId) {
        Object obj = eflowTaskService.getObj(Wrappers.lambdaQuery(EflowTask.class).select(EflowTask::getProcessInstanceId).eq(EflowTask::getBusinessId, businessId).groupBy(EflowTask::getProcessInstanceId), (x) -> x);
        return obj == null ? null : obj.toString();
    }

    @Override
    public void rejected(RejectedTaskVo rejectedTaskVo) {
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(rejectedTaskVo.getTaskId()).singleResult();
        //1.把当前的节点设置为空
        if (taskEntity == null) {
            throw new FlowableException("不存在任务实例,请确认!");
        }
        //5.删除节点
        this.deleteActivity(rejectedTaskVo.getActivityId(), taskEntity.getProcessInstanceId());
        JumpTaskVo jumpTaskVo = new JumpTaskVo();
        jumpTaskVo.setActivityId(rejectedTaskVo.getActivityId());
        jumpTaskVo.setTaskId(rejectedTaskVo.getTaskId());
        jumpTaskVo.setAdmin(false);
        jumpTaskVo.setMessage(rejectedTaskVo.getMessage());
        jumpTaskVo.setUserList(rejectedTaskVo.getUserList());
        managementService.executeCommand(new RejectedCmd(jumpTaskVo, this));
    }

    private List<TaskNodeVo> getOneStepUserTasks(String businessKey, ProcessDefinition processDefinition, Map<String, Object> variables) {

        if (variables == null) {
            variables = new HashMap<>();

        }
        variables.put(FLOW_SUBMIT_TASK_VAL, Authentication.getAuthenticatedUserId());
        //设置流程开始的变量
        Process process = FlowUtil.getProcess(repositoryService, processDefinition.getId());
        Map<String, Object> finalVariables = variables;
        processListener.handle((next) -> {
            Map<String, Object> vars = next.getVariables(businessKey);
            if (vars != null) {
                finalVariables.putAll(vars);
            }
            return true;
        }, process.getId());
        List<Activity> nextUserTasks = FlowUtil.getOneStepUserTasks(repositoryService, processDefinition, variables);
        List<TaskNodeVo> taskNode = getTaskNode(processDefinition, null, variables, nextUserTasks);
        setSkipTask(processDefinition, variables, taskNode);
        return taskNode;
    }

    private void setSkipTask(ProcessDefinition processDefinition, Map<String, Object> variables, List<TaskNodeVo> taskNode) {
        if (CollUtil.isNotEmpty(taskNode) && taskNode.size() == 1) {
            TaskNodeVo taskNodeVo = taskNode.get(0);
            List<EflowUser> userList = taskNodeVo.getUserList();
            if (CollUtil.isNotEmpty(userList) && userList.size() == 1) {
                //如果候选用户是自己且只有一个则跳到下一个节点，并且将此节点设置为跳过
                if (userList.get(0).getUserId().equals(Authentication.getAuthenticatedUserId())||(userList.get(0).isProxy()&&userList.get(0).getProxyUserId().equals(Authentication.getAuthenticatedUserId()))) {
                    taskNodeVo.setSkip(true);
                    //将人员添加到流程变量，指派到节点可能会用到
                    variables.put(taskNodeVo.getNodeId() + "_" + VAR_TASK_USER_LIST, userList);
                    List<Activity> nextUserTasks1 = FlowUtil.getNextUserTasks(repositoryService, processDefinition, taskNodeVo.getNodeId(), variables);
                    taskNode.addAll(getTaskNode(processDefinition, null, variables, nextUserTasks1));
                }
            }
        }
    }

    @Override
    protected void addComment(String taskId, String userCode, String processInstanceId, CommentTypeEnum type, String message) {
        eflowTaskService.update(Wrappers.lambdaUpdate(EflowTask.class)
                .set(EflowTask::getStatus, TaskStatus.END.getCode())
                .set(EflowTask::getComments, message)
                .set(EflowTask::getEndDate, new Date())
                .set(EflowTask::getCommentType, type.getCode())
                .eq(EflowTask::getTaskId, taskId));
    }
}
